﻿using System;
using System.Linq;
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Conventions;

namespace HashFoo.Nhib
{
    /// <summary>
    /// Extension methods for FluentNHibernate <see cref="IConvention"/> configuration.
    /// </summary>
    public static class ConventionsExtensions
    {
        /// <summary>
        /// Adds all Fluent NHibernate conventions except those provided in the <paramref name="excludedConventions"/> list.
        /// </summary>
        /// <typeparam name="TConvention"></typeparam>
        /// <param name="conventionFinder"></param>
        /// <param name="excludedConventions"></param>
        /// <returns></returns>
        public static AutoPersistenceModel AddFromAssemblyOfExcept<TConvention>(
            this SetupConventionFinder<AutoPersistenceModel> conventionFinder,
            params Type[] excludedConventions) where TConvention : IConvention
        {
            var conventionsToUse =
                typeof(TConvention).Assembly
                    .GetTypes()
                    .ToArray()
                    .Where(
                        t =>
                        typeof(IConvention).IsAssignableFrom(t) &&
                        t.IsClass &&
                        t.IsAbstract == false &&
                        t.IsPublic &&
                        excludedConventions.All(excludedType => excludedType != t));

            AutoPersistenceModel autoPersistenceModel = null;
            foreach (var conventionType in conventionsToUse) autoPersistenceModel = conventionFinder.Add(conventionType);

            // we use an empty Add to get back the AutoPersistenceModel if no conventions were found in the assembly.
            return autoPersistenceModel ?? conventionFinder.Add();
        }
    }
}